package com.ng.desktop.view.dieta;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import com.ng.desktop.model.Categoria;
import com.ng.desktop.persistence.CategoriaPersistence;
import com.ng.desktop.services.NGFactoryBean;
import com.ng.framework.view.desktop.table.NGCustomTable;

public class PorcionesPanel extends JPanel {
	

	private static final long serialVersionUID = 5003063948754373323L;

	private static final int COL_CATEGORIA = 0;
	private static final int COL_ENERGIA = 1;
	private static final int COL_CHON = 2;
	private static final int COL_CHO = 3;
	private static final int COL_FAT = 4;
	private static final int COL_PORCIONES = 5;
	private static final int COL_ENERGIA_PORCIONES = 6;
	private static final int COL_CHON_PORCIONES = 7;
	private static final int COL_CHO_PORCIONES = 8;
	private static final int COL_FAT_PORCIONES = 9;
	
	private static final Color RED = new Color(250, 128, 114);
	private static final Color YELLOW = new Color(255, 215, 0);
	private static final Color GREEN = new Color(141, 188, 143);
	private static final Color BLUE = new Color(70, 130, 180);
	
	private Double chon;
	private Double cho;
	private Double fat;
	private Double energia;
	private CategoriaPersistence categoriaPersistence;
	private NGCustomTable tablePorciones;
	private HashMap<Integer, Double> porciones;
	
	public PorcionesPanel() {
		this.porciones = new HashMap<Integer, Double>();
		
		this.buildGui();
	}
	
	private void buildGui() {
		this.setLayout(new GridBagLayout());
		
		JScrollPane scrollPane = new JScrollPane(this.getTablePorciones(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollPane.setBorder(BorderFactory.createTitledBorder("Alimentos, porciones y valor nutricional"));
		this.add(scrollPane, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
	}
	
	private NGCustomTable getTablePorciones() {
		if(tablePorciones == null) {
			this.tablePorciones = new NGCustomTable(new String[] { "Categoría", "Energía", "CHON", "CHO", "FAT", "Porciones", "Energía", "CHON(g)", "CHO(g)", "FAT(g)" });
			
			tablePorciones.getColumnModel().getColumn(0).setPreferredWidth(200);
			
			List<Categoria> categorias = this.getCategoriaPersistence().getAll();
			Collections.sort(categorias, new Comparator<Categoria>() {

				@Override
				public int compare(Categoria o1, Categoria o2) {
					return o1.getNombre().compareTo(o2.getNombre());
				}
			});
			
			for(Categoria categoria : categorias) {
				tablePorciones.addRow(new Object[] { categoria.getNombre(), categoria.getEnergia(), categoria.getChon(), categoria.getFat(), categoria.getEnergia(), 0d, 0d, 0d, 0d, 0d });
				Integer lastRow = tablePorciones.getRowCount() - 1;
				tablePorciones.setCellEditable(lastRow, COL_PORCIONES, true);
				tablePorciones.setCellForeground(lastRow, COL_PORCIONES, BLUE);
				
				porciones.put(lastRow, 0d);
			}
			tablePorciones.setNumericColumn(COL_PORCIONES, Double.class);
			
			tablePorciones.addRow(new Object[] { "Total", null, null, null, null, null, 0d, 0d, 0d, 0d });
			tablePorciones.combine(tablePorciones.getRowCount() - 1, COL_CATEGORIA, 1, 6);
			
			tablePorciones.setCellAlignment(tablePorciones.getRowCount() - 1, COL_CATEGORIA, SwingUtilities.RIGHT);
			
			tablePorciones.getModel().addTableModelListener(new TableModelListener() {
				
				@Override
				public void tableChanged(TableModelEvent e) {
					if(e.getColumn() == COL_PORCIONES && e.getFirstRow() >= 0 && e.getFirstRow() < tablePorciones.getRowCount() - 1) {
						PorcionesPanel.this.updateTable();
					}
				}
			});	
		}
		
		return tablePorciones;
	}
	
	public void updateTable() {
		Double totalEnergia = 0d;
		Double totalChon = 0d;
		Double totalCho = 0d;
		Double totalFat = 0d;
		
		for(int i = 0; i < PorcionesPanel.this.getTablePorciones().getRowCount() - 1; i++) {
			Double porciones = (Double)PorcionesPanel.this.getTablePorciones().getValueAt(i, COL_PORCIONES);
			if(porciones == null) {
				porciones = 0d;
			}
			
			Double energia = porciones * (Double)PorcionesPanel.this.getTablePorciones().getValueAt(i, COL_ENERGIA);
			this.getTablePorciones().setValueAt(energia, i, COL_ENERGIA_PORCIONES);
			totalEnergia += energia;
			
			Double chon = porciones * (Double)PorcionesPanel.this.getTablePorciones().getValueAt(i, COL_CHON);
			this.getTablePorciones().setValueAt(chon, i, COL_CHON_PORCIONES);
			totalChon += chon;
			
			Double cho = porciones * (Double)PorcionesPanel.this.getTablePorciones().getValueAt(i, COL_CHO);
			this.getTablePorciones().setValueAt(cho, i, COL_CHO_PORCIONES);
			totalCho += cho;
			
			Double fat = porciones * (Double)PorcionesPanel.this.getTablePorciones().getValueAt(i, COL_FAT);
			this.getTablePorciones().setValueAt(fat, i, COL_FAT_PORCIONES);
			totalFat += fat;
			
			this.porciones.put(i, porciones);
		}
		
		int lastRow = PorcionesPanel.this.getTablePorciones().getRowCount() - 1;
		
		this.getTablePorciones().setValueAt(totalEnergia, lastRow, COL_ENERGIA_PORCIONES);
		this.getTablePorciones().setValueAt(totalChon, lastRow, COL_CHON_PORCIONES);
		this.getTablePorciones().setValueAt(totalCho, lastRow, COL_CHO_PORCIONES);
		this.getTablePorciones().setValueAt(totalFat, lastRow, COL_FAT_PORCIONES);
		
		this.setForeground(energia, COL_ENERGIA_PORCIONES);
		this.setForeground(chon, COL_CHON_PORCIONES);
		this.setForeground(cho, COL_CHO_PORCIONES);
		this.setForeground(fat, COL_FAT_PORCIONES);
	}
	
	private void setForeground(Double referenceValue, int column) {
		Double actualValue = (Double)getTablePorciones().getValueAt(this.getTablePorciones().getRowCount() - 1, column);
		
		Color foreground;
		if(actualValue < referenceValue) {
			foreground = YELLOW;
		} else if(actualValue > referenceValue) {
			foreground = RED;
		} else {
			foreground = GREEN;
		}
		
		this.getTablePorciones().setCellForeground(this.getTablePorciones().getRowCount() - 1, column, foreground);
	}
	
	private CategoriaPersistence getCategoriaPersistence() {
		if(categoriaPersistence == null) {
			this.categoriaPersistence = (CategoriaPersistence) NGFactoryBean.getInstance().getBean("categoriaPersistence");
		}
		
		return categoriaPersistence;
	}

	public void setChon(Double chon) {
		this.chon = chon;
	}

	public void setCho(Double cho) {
		this.cho = cho;
	}

	public void setFat(Double fat) {
		this.fat = fat;
	}

	public void setEnergia(Double energia) {
		this.energia = energia;
	}

	public HashMap<Integer, Double> getPorciones() {
		return porciones;
	}
	
	public Double getEnergia() {
		return (Double)this.getTablePorciones().getValueAt(this.getTablePorciones().getRowCount() - 1, COL_ENERGIA_PORCIONES);
	}
}
